package gitee.derumin.teleport_compass;

import gitee.derumin.lib_for_derumin.api.features.ChunkDataTools;
import gitee.derumin.lib_for_derumin.helpers.config.ConfigHelper;
import gitee.derumin.lib_for_derumin.logger.DeruminLogger;
import gitee.derumin.teleport_compass.commands.ProtectWaypointCommand;
import gitee.derumin.teleport_compass.waypoints.Waypoints;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.player.AttackBlockCallback;
import net.fabricmc.fabric.api.loot.v2.LootTableEvents;
import net.minecraft.component.DataComponentTypes;
import net.minecraft.component.type.LoreComponent;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.LootTable;
import net.minecraft.loot.entry.ItemEntry;
import net.minecraft.loot.function.SetComponentsLootFunction;
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Identifier;
import net.minecraft.util.Rarity;
import net.minecraft.util.math.BlockPos;

import java.util.ArrayList;
import java.util.List;

public class Teleport_compass implements ModInitializer {
    public static final TCConfig CONFIG = new TCConfig();
    public static final ItemStack TELEPORT_COMPASS;
    public static final ItemStack WAYPOINT_LODESTONE;
    public static final Text COMPASS_NAME_CN;
    public static final Text COMPASS_NAME_TRANSLATE;
    public static final Text COMPASS_NAME_LINKED;
    public static final Text LODESTONE_NAME_CN;
    public static final Text LODESTONE_NAME_TRANSLATE;
    public static final String NAMESPACE;
    private static final Text WARN_CN;
    private static final Text WARN_TRANSLATE;

    static {
        COMPASS_NAME_CN = Text.of("传送指针");
        LODESTONE_NAME_CN = Text.of("引路磁石");
        COMPASS_NAME_TRANSLATE = Text.translatable("item.teleport_compass.teleport_compass");
        LODESTONE_NAME_TRANSLATE = Text.translatable("item.teleport_compass.waypoint_lodestone");
        COMPASS_NAME_LINKED = Text.of("绑定的指针");
        ItemStack compass = Items.COMPASS.getDefaultStack().copy();
        ItemStack lodestone = Items.LODESTONE.getDefaultStack().copy();
        compass.set(DataComponentTypes.RARITY, Rarity.RARE);
        lodestone.set(DataComponentTypes.RARITY, Rarity.EPIC);
        List<Text> lines1 = new ArrayList<>();
        List<Text> lines2 = new ArrayList<>();
        if (CONFIG.internationalization){
            compass.set(DataComponentTypes.ITEM_NAME, COMPASS_NAME_TRANSLATE);
            lodestone.set(DataComponentTypes.ITEM_NAME, LODESTONE_NAME_TRANSLATE);
            lines1.add(Text.translatable("item.teleport_compass.teleport_compass.lore"));
            lines2.add(Text.translatable("item.teleport_compass.waypoint_lodestone.lore1"));
            lines2.add(Text.translatable("item.teleport_compass.waypoint_lodestone.lore2"));
            lines2.add(Text.translatable("item.teleport_compass.waypoint_lodestone.lore3"));
            lines2.add(Text.translatable("item.teleport_compass.waypoint_lodestone.lore4"));
        }else {
            compass.set(DataComponentTypes.ITEM_NAME, COMPASS_NAME_CN);
            lodestone.set(DataComponentTypes.ITEM_NAME, LODESTONE_NAME_CN);
            lines1.add(Text.of("右击一个路标来绑定它。"));
            lines2.add(Text.of("可以用于放置一个路标。"));
            lines2.add(Text.of("只能放置于至少两格空气下。"));
            lines2.add(Text.of("无法回收。"));
            lines2.add(Text.of("重命名此物品可以设定路标的名称。"));
        }
        compass.set(DataComponentTypes.LORE, new LoreComponent(lines1));
        lodestone.set(DataComponentTypes.LORE, new LoreComponent(lines2));
        TELEPORT_COMPASS = compass;
        WAYPOINT_LODESTONE = lodestone;
        NAMESPACE = "teleport_compass";
        WARN_CN = Text.of("你正在尝试拆除一个路标。确定要这么做吗?");
        WARN_TRANSLATE = Text.translatable("block.teleport_compass.waypoint.break");
    }

    /**
     * Runs the mod initializer.
     */
    @Override
    public void onInitialize() {
        ConfigHelper.register(CONFIG, NAMESPACE);
        Waypoints.init();
        ProtectWaypointCommand.init();
        ServerTickEvents.START_SERVER_TICK.register(server -> {
            if (CONFIG.benefitsTimeRemains > 0) {
                --CONFIG.benefitsTimeRemains;
            }
            server.getPlayerManager().getPlayerList().forEach(player -> {
                if (!player.getCommandTags().contains("notNewbie_tpCompass")){
                    player.addCommandTag("notNewbie_tpCompass");
                    if (CONFIG.benefitsTimeRemains != 0) {
                        player.getInventory().insertStack(TELEPORT_COMPASS.copyWithCount(CONFIG.benefitsCompassCount));
                        player.getInventory().insertStack(WAYPOINT_LODESTONE.copyWithCount(CONFIG.benefitsLodestoneCount));
                    }
                }
            });
        });
        AttackBlockCallback.EVENT.register((player, world, hand, pos, direction) -> {
            if (!player.isSpectator()){
                Waypoints waypoints = (Waypoints) ChunkDataTools.getExtraData(world, pos, Waypoints.ID);
                if (waypoints != null && waypoints.hasWaypoint(pos)){
                    if (player.isCreative()){
                        DeruminLogger.getLogger().warn(
                                player.getName().getString()
                                        + " 尝试摧毁位于 '"
                                        + pos.toShortString()
                                        + "的路标'"
                                        + waypoints.getWaypointName(pos)
                                        + "'。",
                                DeruminLogger.AnnounceType.ALL);
                    }else {
                        player.sendMessage(CONFIG.internationalization ? WARN_TRANSLATE : WARN_CN, true);
                    }
                }
            }
            return ActionResult.PASS;
        });
        Identifier id1 = Identifier.of(NAMESPACE, "teleport_compass");
        Identifier id2 = Identifier.of(NAMESPACE, "waypoint_lodestone");
        LootTableEvents.REPLACE.register((key, original, source) -> {
            if (key.getValue().equals(id1)){
                return LootTable.builder().pool(LootPool.builder()
                                .rolls(ConstantLootNumberProvider.create(1))
                                .with(ItemEntry.builder(Items.COMPASS)
                                        .apply(SetComponentsLootFunction.builder(DataComponentTypes.ITEM_NAME, TELEPORT_COMPASS.get(DataComponentTypes.ITEM_NAME)))
                                        .apply(SetComponentsLootFunction.builder(DataComponentTypes.RARITY, TELEPORT_COMPASS.get(DataComponentTypes.RARITY)))
                                        .apply(SetComponentsLootFunction.builder(DataComponentTypes.LORE, TELEPORT_COMPASS.get(DataComponentTypes.LORE)))))
                        .build();
            }
            if (key.getValue().equals(id2)){
                return LootTable.builder()
                        .pool(LootPool.builder()
                                .rolls(ConstantLootNumberProvider.create(1))
                                .with(ItemEntry.builder(Items.LODESTONE)
                                        .apply(SetComponentsLootFunction.builder(DataComponentTypes.ITEM_NAME, WAYPOINT_LODESTONE.get(DataComponentTypes.ITEM_NAME)))
                                        .apply(SetComponentsLootFunction.builder(DataComponentTypes.RARITY, WAYPOINT_LODESTONE.get(DataComponentTypes.RARITY)))
                                        .apply(SetComponentsLootFunction.builder(DataComponentTypes.LORE, WAYPOINT_LODESTONE.get(DataComponentTypes.LORE)))))
                        .build();
            }
            return null;
        });

    }

    public static boolean isTeleportCompass(ItemStack stack){
        if (stack.isEmpty()){
            return false;
        }
        Text text = stack.get(DataComponentTypes.ITEM_NAME);
        return COMPASS_NAME_CN.equals(text) || COMPASS_NAME_TRANSLATE.equals(text);
    }

    public static boolean isLinkedCompass(ItemStack stack){
        if (stack.isEmpty()){
            return false;
        }
        Text text = stack.get(DataComponentTypes.ITEM_NAME);
        return COMPASS_NAME_LINKED.equals(text);
    }

    public static boolean isWaypointLodestone(ItemStack stack){
        if (stack.isEmpty()){
            return false;
        }
        Text text = stack.get(DataComponentTypes.ITEM_NAME);
        return LODESTONE_NAME_CN.equals(text) || LODESTONE_NAME_TRANSLATE.equals(text);
    }

    public static Text getDefaultWaypointName(BlockPos pos){
        return (CONFIG.internationalization? Text.translatable("block.teleport_compass.waypoint").append(pos.toShortString()) : Text.of("路标" + pos.toShortString()));
    }
}
